/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "framework/list.h"

namespace air {
namespace link {

// init
void List::Init() {
  m_root_.prev = m_root_.next = &m_root_;
  m_count_ = 0;
}

// add
void List::Add(Node* prev, Node* next, Node* node) {
  if (!node) return;
  ++m_count_;
  prev->next = node;
  next->prev = node;
  node->prev = prev;
  node->next = next;
}

void List::AddHead(Node* node) { Add(&m_root_, m_root_.next, node); }

void List::AddTail(Node* node) { Add(m_root_.prev, &m_root_, node); }

// del
void List::Del(Node* prev, Node* next, bool b) {
  --m_count_;
  if (b) delete prev->next;
  prev->next = next;
  next->prev = prev;
}

void List::Del(Node* node, bool b) {
  Del(node->prev, node->next, b);
  node->prev = node->next = node;
}

void List::DelHead(bool b) {
  if (IsEmpty()) return;
  Del(m_root_.next, b);
}

void List::DelTail(bool b) {
  if (IsEmpty()) return;
  Del(m_root_.prev, b);
}

void List::DelWithIndex(int index, bool b) {
  if (IsEmpty()) return;
  Node* temp;

  temp = GetData(index);
  if (temp) Del(temp->prev, temp->next, b);
}

// move append函数
void List::MoveHead(Node* node) {
  Del(node->prev, node->next, false);
  AddHead(node);
}

void List::MoveTail(Node* node) {
  Del(node->prev, node->next, false);
  AddTail(node);
}

void List::Append(List* from) {
  if (from->IsEmpty()) return;
  Node* f_head = from->m_root_.next;
  Node* f_tail = from->m_root_.prev;

  m_root_.prev->next = f_head;
  f_head->prev = m_root_.prev;

  f_tail->next = &m_root_;
  m_root_.prev = f_tail;

  m_count_ += from->m_count_;
  // must invoke this method
  from->Init();
}

Node* List::GetData(int index) {
  if (IsEmpty()) return &m_root_;
  if (index < 0 || index >= m_count_) return nullptr;

  Node* temp = &m_root_;
  int temp_index = -1;

  if (index >= m_count_ / 2) {  // 使用倒序遍历
    temp_index = m_count_;
    do {
      if (index != temp_index) {
        --temp_index;
        temp = temp->prev;
      } else {
        return temp;
      }
    } while (true);
  } else {  // 使用正序遍历
    temp_index = -1;
    do {
      if (index != temp_index) {
        ++temp_index;
        temp = temp->next;
      } else {
        return temp;
      }
    } while (true);
  }
}

void List::Clear(bool b) {
  while (!IsEmpty()) {
    DelHead(b);
  }
  m_count_ = 0;
}

}  // namespace link
}  // namespace air
